import React, { useRef, useState, useMemo } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { OrbitControls, MeshReflectorMaterial } from "@react-three/drei";
import * as THREE from "three";

function ConeTrail({ points, ballRadius }) {
  const meshRef = useRef();
  // 使用useMemo来缓存几何体，避免每帧重建
  const geometry = useMemo(() => {
    if (points.length < 2) return new THREE.BufferGeometry();

    // 创建弯曲的圆锥形拖尾
    const geometry = new THREE.BufferGeometry();
    const positions = [];
    const indices = [];
    const colors = [];
    const radialSegments = 30; // 圆周分段数
    const pathSegments = Math.min(points.length, 50); // 增加路径分段数

    // 首先计算路径上的点
    const pathPoints = [];
    for (let i = 0; i < pathSegments; i++) {
      // 使用曲线补间来平滑路径
      if (i < points.length) {
        pathPoints.push(points[i]);
      }
    }

    // 为路径上的每个点创建圆形截面
    for (let i = 0; i < pathPoints.length; i++) {
      const t = i / (pathPoints.length - 1); // 归一化路径位置
      const currentPoint = pathPoints[i];

      // 确定当前点的朝向
      let direction;
      if (i < pathPoints.length - 1) {
        direction = new THREE.Vector3()
          .subVectors(pathPoints[i + 1], currentPoint)
          .normalize();
      } else if (i > 0) {
        direction = new THREE.Vector3()
          .subVectors(currentPoint, pathPoints[i - 1])
          .normalize();
      } else {
        direction = new THREE.Vector3(0, 0, -1);
      }

      // 创建垂直于方向的平面
      const normal = direction.clone();
      const binormal = new THREE.Vector3(0, 1, 0).cross(normal).normalize();
      const tangent = normal.clone().cross(binormal).normalize();

      // 计算当前位置的圆锥半径 (从球体半径开始，到尾部变为0)
      const radius = ballRadius * (1 - Math.pow(t, 1.5));

      // 在圆周上创建顶点
      for (let j = 0; j < radialSegments; j++) {
        const theta = (j / radialSegments) * Math.PI * 2;
        const vx = Math.cos(theta);
        const vy = Math.sin(theta);

        // 圆形截面上的点
        const px = currentPoint.x + radius * (vx * tangent.x + vy * binormal.x);
        const py = currentPoint.y + radius * (vx * tangent.y + vy * binormal.y);
        const pz = currentPoint.z + radius * (vx * tangent.z + vy * binormal.z);

        positions.push(px, py, pz);

        // 颜色 (从不透明到透明)
        const alpha = 1.0 - Math.pow(t, 0.7);
        colors.push(0, 1, 1, alpha); // 青色 + alpha
      }
    }

    // 创建三角形索引
    for (let i = 0; i < pathPoints.length - 1; i++) {
      const baseIndex = i * radialSegments;
      for (let j = 0; j < radialSegments; j++) {
        const a = baseIndex + j;
        const b = baseIndex + ((j + 1) % radialSegments);
        const c = baseIndex + j + radialSegments;
        const d = baseIndex + ((j + 1) % radialSegments) + radialSegments;

        // 添加两个三角形组成一个四边形面
        indices.push(a, b, c);
        indices.push(c, b, d);
      }
    }

    // 设置顶点和索引
    geometry.setIndex(indices);
    geometry.setAttribute(
      "position",
      new THREE.Float32BufferAttribute(positions, 3)
    );
    geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 4));

    // 计算法线以获得更好的光照效果
    geometry.computeVertexNormals();

    return geometry;
  }, [points, ballRadius]);

  return (
    <mesh ref={meshRef} geometry={geometry}>
      <meshBasicMaterial
        vertexColors
        transparent
        depthWrite={false}
        blending={THREE.AdditiveBlending}
        side={THREE.DoubleSide}
      />
    </mesh>
  );
}

function ReflectiveGround() {
  return (
    <mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, 0, 0]} >
      <planeGeometry args={[30, 30]} />
      <MeshReflectorMaterial
        blur={[0, 100]}
        resolution={1024}
        mixBlur={1}
        mixStrength={15}
        depthScale={1}
        minDepthThreshold={0.85}
        color="#f0f0f0"
        metalness={0.6}
        roughness={0.2}
        mirror={0.75}
      />
    </mesh>
  );
}

function GlowingBall({
  path = [],
  speed = 1,
}) {
  const BALL_RADIUS = 0.3;
  const mesh = useRef();
  const glowRef = useRef();
  const [trail, setTrail] = useState([]);
  const TRAIL_LENGTH = 30;

  const [currentIndex, setCurrentIndex] = useState(0)
  const TRAIL_SPACING = 0.1;

  const tRef = useRef(0)

  useFrame((_, delta) => {
    if (!mesh.current || currentIndex >= path.length - 1) return

    tRef.current += delta * speed
    let t = tRef.current
    if (t > 1) {
      tRef.current = 0
      setCurrentIndex((prev) => prev + 1)
      return
    }

    const start = new THREE.Vector3(...path[currentIndex])
    const end = new THREE.Vector3(...path[currentIndex + 1])
    const pos = new THREE.Vector3().lerpVectors(start, end, t)
    pos.y += Math.sin(Math.PI * t) * 1.5 // 跳跃高度

    mesh.current.position.copy(pos)

    // 同步外部发光层位置
    if (glowRef.current) {
      glowRef.current.position.copy(pos);
    }

    // 更新拖尾效果
    setTrail((prev) => {
      if (prev.length === 0) return [pos.clone()];
      const lastPos = prev[0];
      if (lastPos.distanceTo(pos) < TRAIL_SPACING) {
        return prev;
      }
      const next = [pos.clone(), ...prev];
      return next.length > TRAIL_LENGTH ? next.slice(0, TRAIL_LENGTH) : next;
    });
  });

  return (
    <>
      {/* 核心球体 */}
      <mesh ref={mesh} castShadow>
        <sphereGeometry args={[BALL_RADIUS, 32, 32]} />
        <meshStandardMaterial
          color="#00ffff"
          emissive="#00ffff"
          emissiveIntensity={5}
          metalness={0.9}
          roughness={0.1}
        />
      </mesh>

      {/* 外部发光层 */}
      <mesh ref={glowRef}>
        <sphereGeometry args={[BALL_RADIUS * 1.05, 32, 32]} />
        <meshBasicMaterial
          color="#80ffff"
          transparent
          opacity={0.6}
          blending={THREE.AdditiveBlending}
          depthWrite={false}
        />
      </mesh>

      {trail.length >= 2 && (
        <ConeTrail points={trail} ballRadius={BALL_RADIUS} />
      )}
    </>
  );
}

export default function App() {
  return (
    <div style={{ width: "100vw", height: "100vh", background: "#000" }}>
      <Canvas camera={{ position: [-12, 12, 12], fov: 50 }} shadows>
        <color attach="background" args={["#999999"]} />
        <ambientLight intensity={0.3} />
        <pointLight position={[0, 5, 5]} intensity={2} castShadow />
        {/* 第一个小球从左侧移动到右侧 */}
        <GlowingBall
          path={[
            [0, 0, 0],
            [2, 0, 1],
            [4, 0, 0],
            [6, 0, -1],
            [8, 0, 0],
          ]}
          duration={2}
        />
        {/* 第二个小球从右侧移动到左侧 */}
        <GlowingBall
          path={[
            [8, 0, 0],
            [6, 0, 1],
            [4, 0, 2],
            [2, 0, 1],
            [0, 0, 0]
          ]}
          duration={3}
        />
        <ReflectiveGround />
        <OrbitControls />
      </Canvas>
    </div>
  );
}
